using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using NSMBe4;
using System.IO;

namespace MKDS_Course_Editor
{
    public partial class CoursePictureGenerator : Form
    {
        public CoursePictureGenerator()
        {
            InitializeComponent();
            System.Drawing.Imaging.PixelFormat e = new System.Drawing.Imaging.PixelFormat();
            toolStripComboBox1.Items.AddRange(Enum.GetNames(e.GetType()));
            toolStripComboBox1.SelectedIndex = 5;
            toolStripComboBox2.Items.AddRange(Enum.GetNames(e.GetType()));
            toolStripComboBox2.SelectedIndex = 5;
        }
        List<Color> pal;
        Bitmap image;
        int[] paltilenr;
        //int[] pcindex;
        private void toolStripButton1_Click(object sender, EventArgs e)
        {
            if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && openFileDialog1.FileName.Length > 0)
            {
                toolStripButton2.Enabled = true;
                toolStripButton3.Enabled = true;
                toolStripButton4.Enabled = true;
                toolStripButton5.Enabled = true;
                button1.Enabled = true;
                label1.Enabled = true;
                Bitmap newImage = new Bitmap(80, 88);
                using (Graphics gr = Graphics.FromImage(newImage))
                {
                    gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                    gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                    gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                    gr.Clear(Color.FromArgb(240, 152, 192));
                    gr.DrawImage(Bitmap.FromFile(openFileDialog1.FileName), new Rectangle(4, 0, 70, 88), new Rectangle(0, 0, 70, 88), GraphicsUnit.Pixel);
                }
                pictureBox2.Image = newImage;
                try
                {
                    /*BackgroundWorker bw = new BackgroundWorker();
                    bw.WorkerReportsProgress = true;
                    bw.WorkerSupportsCancellation = true;
                    bw.DoWork +=new DoWorkEventHandler(generate);
                    bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
                    bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                    bw.RunWorkerAsync(new object[] { openFileDialog1.FileName, toolStripComboBox1.SelectedIndex, toolStripComboBox2.SelectedIndex });*/
                    //bwr = bw;
                    //toolStripDropDownButton1.Enabled = true;


                    //listBox1.SetSelected(listBox1.SelectedIndex, true);
                    //generate();
                }
                catch (Exception ex)
                {
                    toolStripButton2.Enabled = false;
                    toolStripButton3.Enabled = false;
                    toolStripButton4.Enabled = false;
                    MessageBox.Show("error");
                }
            }
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            object[] o = (object[])e.Result;
            pal = (List<Color>)o[0];
            image = (Bitmap)o[1];
            paltilenr = (int[])o[2];
            pictureBox1.Image = (Bitmap)o[1];
        }

        void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            try
            {
                toolStripProgressBar1.Value = e.ProgressPercentage;
            }
            catch
            {

            }
            toolStripStatusLabel1.Text = (string)e.UserState;
        }
        void generate(object sender, DoWorkEventArgs e)
        {
            object[] o = (object[])e.Argument;
            Bitmap b = new Bitmap((string)o[0]);
            BackgroundWorker bw = (BackgroundWorker)sender;
            Bitmap newImage = new Bitmap(80, 88, /*System.Drawing.Imaging.PixelFormat.Format16bppRgb555*/(System.Drawing.Imaging.PixelFormat)Enum.GetValues(new System.Drawing.Imaging.PixelFormat().GetType()).GetValue((int)o[1]));
            using (Graphics gr = Graphics.FromImage(newImage))
            {
                gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                //gr.FillRectangle(new SolidBrush(Color.FromArgb(240, 152, 192)), 0, 0, 256, 256);
                // gr.DrawImage(b, new Rectangle(0, 0, (int)((float)width * ((float)b.Height / (float)b.Width)), (int)((float)height * ((float)b.Height / (float)b.Width))));
                gr.DrawImage(b, new Rectangle(4, 0, 70, 88), new Rectangle(0, 0, 70, 88), GraphicsUnit.Pixel);
                /*gr.DrawImage(b, new Rectangle(252, 64, 4, 75), new Rectangle(0, 8, 4, 75), GraphicsUnit.Pixel);
                for (int i = 0; i < 8; i++)
                {
                    for (int j = 4; j < 256; j += 8)
                    {
                        gr.DrawImage(b, new Rectangle(j, i * 8, 4, 8), new Rectangle(0, 0, 4, 8), GraphicsUnit.Pixel);
                    }
                }
                for (int i = 8; i < 19; i++)
                {
                    for (int j = 4; j < 176; j += 8)
                    {
                        gr.DrawImage(b, new Rectangle(j, i * 8, 4, 8), new Rectangle(0, 0, 4, 8), GraphicsUnit.Pixel);
                    }
                }
                for (int i = 19; i < 32; i++)
                {
                    for (int j = 4; j < 256; j += 8)
                    {
                        gr.DrawImage(b, new Rectangle(j, i * 8, 4, 8), new Rectangle(0, 0, 4, 8), GraphicsUnit.Pixel);
                    }
                }*/
            }
            b = newImage;
            bw.ReportProgress(1, "Tiling Image");
            ImageTiler t = new ImageTiler(b, Convert.ToInt32(toolStripTextBox1.Text));
            bw.ReportProgress(2, "Creating a new Picture");
            //MessageBox.Show((t.tileBuffer.Width / 8).ToString());
            /*Bitmap b5_ = new Bitmap(80, 88);
            NSMBe4.NSBMD.ImageTexeler.LockBitmap b5 = new NSMBe4.NSBMD.ImageTexeler.LockBitmap(b5_);
            b5.LockBits();
            for (int i = 0; i < 11; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    for (int k = 0; k < 8; k++)
                    {
                        for (int l = 0; l < 8; l++)
                        {
                            b5.SetPixel(j * 8 + l, i * 8 + k, t.tileBuffer.GetPixel(t.tileMap[j, i] * 8 + l, k));
                        }
                    }
                }
            }
            b5.UnlockBits();
            bw.ReportProgress(10, "Generate a palette for each tile");
            b = b5_;*/
            List<Color> c = new List<Color>();
            List<Color[]> col = new List<Color[]>();
            Color[,][] c2 = new Color[11, 10][];
            List<int> palnr = new List<int>();
            /*for (int i = 0; i < 8; i++)
            {
                c[i, 0] = Color.FromArgb(240, 152, 192);
                for (int j = 0; j < 16; j++)
                {
                    Bitmap ni = new Bitmap(8, 8);
                    using (Graphics gr = Graphics.FromImage(ni))
                    {
                        gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
                        gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                        gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                        gr.DrawImage(b, new Rectangle(0, 0, 8, 8), new Rectangle(0, 8, 4, 75), GraphicsUnit.Pixel);
                    }
                    ImageIndexer.createPaletteForImage(ni, 15);
                }
            }*/
            /*or (int i = 0; i < 88; i += 8)
            {
                for (int j = 0; j < 80; j += 8)
                {
                    Bitmap ni = new Bitmap(8, 8, (System.Drawing.Imaging.PixelFormat)Enum.GetValues(new System.Drawing.Imaging.PixelFormat().GetType()).GetValue((int)o[2]));
                    using (Graphics gr = Graphics.FromImage(ni))
                    {
                        gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                        gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        gr.DrawImage(b, new Rectangle(0, 0, 8, 8), new Rectangle(j, i, 8, 8), GraphicsUnit.Pixel);
                    }
                    Bitmap ni2 = new Bitmap(8, 8);
                    NSMBe4.NSBMD.ImageTexeler.LockBitmap llll = new NSMBe4.NSBMD.ImageTexeler.LockBitmap(ni2);
                    llll.LockBits();
                    for (int k = 0; k < 8; k++)
                    {
                        for (int l = 0; l < 8; l++)
                        {
                            llll.SetPixel(k, l, ni.GetPixel(k, l));
                        }
                    }
                    llll.UnlockBits();
                    c2[i / 8, j / 8] = ImageIndexer.createPaletteForImage(ni2, 16, true);
                }
            }*/
            bw.ReportProgress(20, "Look for similar palettes");
            /*for (int i = 0; i < 11; i++)
            {
                for (int j = 0; j < 10; j++)
                {
                    Color[] Co = c2[i, j];
                    int con = contains(col.ToArray(), Co);
                    if (con == -1)
                    {
                        col.Add(Co);
                    }
                    palnr.Add((con == -1 ? col.IndexOf(Co) : con));
                }
            }*/
            bw.ReportProgress(30, "Scale the palette down - 0%");
            float percent = 30;
            float percent2 = 0;
            float add = 65f / (float)(col.Count - 7);
            float add2 = 100f / (float)(col.Count - 7);
            /*while (col.Count > 7)
            {
                //Console.Out.WriteLine(countUsedPalettes());
                int besta = -1;
                int bestb = -1;
                float bestDif = float.MaxValue;

                //Find the two most similar palettes
                for (int i = 0; i < col.Count; i++)
                {
                    //if (paletteCounts[i] == 0) continue;
                    for (int j = 0; j < col.Count; j++)
                    {
                        if (i == j) continue;

                        float p = palDif(col[i], col[j]);
                        if (p < bestDif)
                        {
                            bestDif = p;
                            besta = j;
                            bestb = i;
                        }

                        //if (paletteCounts[j] == 0) continue;

                        /*if (paletteDiffs[i, j] < bestDif)
                        {
                            bestDif = paletteDiffs[i, j];
                            besta = j;
                            bestb = i;
                        }/

                    }
                }
                col[besta] = palMerge(col[besta], col[bestb]);
                col.RemoveAt(bestb);
                palnrR(palnr, besta, bestb);
                bw.ReportProgress((int)percent, "Scale the palette down - " + percent2.ToString("000") + "%");
                percent += add;
                percent2 += add2;
            }*/
            Color[][] palsel = new Color[7][];
            palsel[0] = null;
            palsel[1] = null;
            palsel[2] = null;
            palsel[3] = null;
            palsel[4] = null;
            palsel[5] = null;
            palsel[6] = null;
            for (int nr = 0; nr < 7; nr++)
            {
                Bitmap nrrr = null;
                for (int i = 0; i < 10; i++)
                {
                    for (int j = 0; j < 11; j++)
                    {
                        if (selectedpalettes[i, j] == nr)
                        {
                            if (nrrr == null)
                            {
                                nrrr = new Bitmap(8, 8);
                            }
                            else
                            {
                                nrrr = new Bitmap(nrrr, nrrr.Width+8, 8);
                            }
                            using (Graphics gr = Graphics.FromImage(nrrr))
                            {
                                gr.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                gr.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                                gr.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                                gr.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                                gr.DrawImage(b, new Rectangle(nrrr.Width-8, 0, 8, 8), new Rectangle(i * 8, j * 8, 8, 8), GraphicsUnit.Pixel);
                            }
                            /*if (palsel[selectedpalettes[i, j]] == null)
                            {
                                palsel[selectedpalettes[i, j]] = c2[j, i];
                            }
                            else
                            {
                                palsel[selectedpalettes[i, j]] = palMerge(palsel[selectedpalettes[i, j]], c2[j, i]);
                            }*/
                        }
                    }
                }
                palsel[nr] = ImageIndexer.createPaletteForImage(nrrr, 16, true);
            }
            bw.ReportProgress(95, "Make the final palette");
            for (int i = 0; i < 7; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    // if (col[i][j] == Color.FromArgb(240, 152, 192)) { col[i][j] = Color.FromArgb(241, 152, 192); }
                    c.Add(palsel[i][j]);
                }
                c[i * 16] = Color.FromArgb(240, 152, 192);
            }
            for (int i = 0; i < 9; i++)
            {
                for (int j = 0; j < 16; j++)
                {
                    c.Add(Color.Black);
                }
            }
            bw.ReportProgress(99, "Generate preview picture");
            //List<int> t = palnr.GetRange(1, palnr.Count - 1);
            //t.Add(palnr[0]);
            //palnr = t;
            // List<int> pixelcolorindex = new List<int>();
            Bitmap b2_ = new Bitmap(80, 88);
            NSMBe4.NSBMD.ImageTexeler.LockBitmap b2 = new NSMBe4.NSBMD.ImageTexeler.LockBitmap(b2_);
            b2.LockBits();
            for (int i = 0; i < 88; i++)
            {
                for (int j = 0; j < 80; j++)
                {
                    b2.SetPixel(j, i, c[closest(b.GetPixel(j, i), c.GetRange((selectedpalettes[(j / 8),(i / 8)] * 16), 16).ToArray()) + selectedpalettes[(j / 8),(i / 8)]*16]);
                    // pixelcolorindex.Add(ImageIndexer.closest(b.GetPixel(j, i), c.GetRange((palnr[(i / 8) * 10 + (j / 8)] * 16), 16).ToArray()) + palnr[(i / 8) * 10 + (j / 8)]);
                }
            }
            b2.UnlockBits();
            //nclr_e es = new nclr_e(c.ToArray(), false, 0);
            //es.ShowDialog();
            object[] ob = new object[] { c, b2_, palnr.ToArray() };
            // pal = c;
            // image = b2;
            // paltilenr = palnr.ToArray();
            // pcindex = pixelcolorindex.ToArray();
            // pictureBox1.Image = b2;
            e.Result = ob;
            bw.ReportProgress(100, "Done");
        }
        public byte closest(Color c, Color[] palette)
        {
            int best = 0;
            float bestDif = float.MaxValue;//colorDifference(c, palette[0]);
            for (int i = 1; i < palette.Length; i++)
            {
                float dif = colorDifference(c, palette[i]);
                if (dif < bestDif)
                {
                    bestDif = dif;
                    best = i;
                }
            }
            if (best >= 256)
                Console.Out.WriteLine("GRAAH");
            return (byte)best;
        }
        public static float colorDifference(Color a, Color b)
        {
            if (a.A != b.A) return float.MaxValue;

            float res = 0;
            res += (a.R - b.R) * (a.R - b.R) / 40;
            res += (a.G - b.G) * (a.G - b.G) / 40;
            res += (a.B - b.B) * (a.B - b.B) / 40;

            if (res > float.MaxValue)
                return float.MaxValue;

            return res;
        }
        public void palnrR(List<int> palnr, int besta, int bestb)
        {
            if (besta > bestb)
            {
                besta--;
            }
            for (int i = 0; i < palnr.Count; i++)
            {
                if (palnr[i] == bestb)
                {
                    palnr[i] = besta;
                }
                else if (palnr[i] > bestb)
                {
                    palnr[i]--;
                }
            }
        }

        public Color[] palMerge(Color[] a, Color[] b)
        {

            Color[] pal = new Color[16];

            /* int one = 0;
             int two = 0;
             for (int i = 0; i < a.Length; i++)
             {

                 int tdiff = (b[i].R - a[i].R) + (b[i].G - a[i].G) + (b[i].B - a[i].B);
                 if (tdiff == 0)
                     one++;
                 else if (tdiff < 0)
                     two++;
                 else
                 {

                     two++;
                 }

             }
             return one >= two ? a : b;*/
            Bitmap bi = new Bitmap(30, 1);
            for (int i = 0; i < 15; i++)
            {
                bi.SetPixel(i, 0, a[i+1]);
                bi.SetPixel(i + 15, 0, b[i+1]);
            }
            return ImageIndexer.createPaletteForImage(bi, 16, true);
        }
        public float palDif(Color[] a, Color[] b)
        {
            return palDifUni(a, b);/*+palDifUni(b, a);*/
        }

        public float palDifUni(Color[] a, Color[] b)
        {
            // bool aTransp = a[16] == Color.Transparent;
            //bool bTransp = b[16] == Color.Transparent;

            //  if (aTransp != bTransp) return float.PositiveInfinity;

            float dif = 0;
            int len = 16;//aTransp ? 16 : 16;

            bool[] sel = new bool[len];

            for (int i = 0; i < len; i++)
            {
                Color c = a[i];
                float diff = float.PositiveInfinity;
                int i2 = -1;
                for (int j = 0; j < len; j++)
                {
                    if (sel[j]) continue;
                    float diff2 = ImageIndexer.colorDifference(c, b[j]);
                    if (diff2 < diff || i2 == -1)
                    {
                        i2 = j;
                        diff = diff2;
                    }
                }
                sel[i2] = true;
                dif += diff;
            }

            return dif;
        }
        public int contains(Color[][] c, Color[] a)
        {
            for (int i = 0; i < c.Length; i++)
            {
                int equals = 0;
                for (int j = 0; j < c[i].Length; j++)
                {
                    if (c[i][j] == a[j])
                    {
                        equals += 1;
                    }
                }
                if (equals == c[i].Length)
                {
                    return i;
                }
            }
            return -1;
        }

        private void toolStripButton2_Click(object sender, EventArgs e)
        {
            if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && saveFileDialog1.FileName.Length > 0)
            {
                EndianBinaryWriter er = new EndianBinaryWriter(File.Create(saveFileDialog1.FileName), Endianness.LittleEndian);
                er.Write("RLCN", Encoding.ASCII, false);
                er.Write(new byte[] { 0xFF, 0xFE, 0x00, 0x01 }, 0, 4);
                Color[] c3 = pal.ToArray();
                List<Int16> palbyte = new List<Int16>();
                nclr_e n = new nclr_e();
                for (int i = 0; i < c3.Length; i++)
                {
                    Color color = c3[i];
                    int nc = 0;
                    nc = n.encodeColor(color.ToArgb(), n.BGR555);
                    palbyte.Add((Int16)nc);
                }
                er.Write(40 + (palbyte.Count * 2));
                er.Write((short)0x10);
                er.Write((short)1);

                er.Write(new byte[] { 0x54, 0x54, 0x4C, 0x50 }, 0, 4);
                er.Write(24 + (palbyte.Count * 2));
                er.Write((short)3);
                er.Write((ushort)0);
                er.Write(new byte[] { 0x00, 0x00, 0x00, 0x00 }, 0, 4);
                er.Write(palbyte.Count * 2);
                er.Write(16);
                er.Write(palbyte.ToArray(), 0, palbyte.Count);
                er.Close();
            }
        }

        private void toolStripButton3_Click(object sender, EventArgs e)
        {
            if (saveFileDialog2.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && saveFileDialog2.FileName.Length > 0)
            {
                EndianBinaryWriter er = new EndianBinaryWriter(File.Create(saveFileDialog2.FileName), Endianness.LittleEndian);
                er.Write("RGCN", Encoding.ASCII, false);
                er.Write(new byte[] { 0xFF, 0xFE, 0x00, 0x01 }, 0, 4);
                er.Write((Int32)0);
                er.Write((short)0x10);
                er.Write((short)0x2);
                // ImageTiler t = new ImageTiler(image);
                er.Write("RAHC", Encoding.ASCII, false);
                er.Write((Int32)0);
                er.Write((Int16)11);
                er.Write((Int16)10);
                er.Write((Int32)3);
                er.Write((ushort)0);
                er.Write((ushort)0);
                er.Write((Int32)0);


                //byte[] b = ImageIndexer.indexImageWithPalette(t.tileBuffer, pal.ToArray());

                List<int> palnr = new List<int>();
                palnr.AddRange(paltilenr);
                /* for (int i = 0; i < 11; i++)
                 {
                     for (int j = 0; j < 10; j++)
                     {
                         palnr[t.tileMap[j, i]] = paltilenr[i * 32 + j];
                     }
                 }*/
                /*byte[] by = new byte[t.tileBuffer.Height * t.tileBuffer.Width];
                int nr = 0;
                int nr2 = 0;
                for (int i = 0; i < t.tileBuffer.Height; i++)
                {
                    for (int j = 0; j < t.tileBuffer.Width; j++)
                    {
                        int c = ImageIndexer.closest(t.tileBuffer.GetPixel(j, i), pal.GetRange((palnr[(i / 8) * (t.tileBuffer.Height / 8) + (j / 8)] * 16), 16).ToArray()) + palnr[(i / 8) * 32 + (j / 8)];
                        //int c2 = ImageIndexer.closest(t.tileBuffer.GetPixel(j, i), pal.GetRange((palnr[(i / 8) * (t.tileBuffer.Height / 8) + (j / 8)] * 16), 16).ToArray()) + palnr[(i / 8) * 32 + (j / 8)];
                       // byte b2 = 0;
                        by[nr] = nr2 == 0 ? (byte)(c & 0xf) : (byte)(c >> 4 & 0xf);
                        //b2 |= (byte)(c2 >> 4 & 0xf);
                        //er.Write((byte)b2);
                        if (nr2 == 0)
                        {
                            nr2++;
                        }
                        else
                        {
                            nr2 = 0;
                            nr++;
                        }
                    }
                }*/
                byte[] palettedImage = new byte[80 * 88 / 2];
                int tileCount = 80 * 88 / 64;
                int tileWidth = 80 / 8;
                int nr = 0;
                int nr2 = 0;
                for (int ti = 0; ti < tileCount; ti++)
                    for (int y = 0; y < 8; y++)
                        for (int x = 0; x < 8; x++)
                        {
                            int tx = (ti % tileWidth) * 8;
                            int ty = (int)(ti / tileWidth) * 8;
                            //palettedImage[ti * 64 + y * 8 + x] =
                            //    imageData[tx + x, ty + y];
                            int c = ImageIndexer.closest(image.GetPixel(tx + x, ty + y), pal.GetRange((selectedpalettes[tx/8,ty/8] * 16), 16).ToArray());
                            palettedImage[nr] |= (nr2 == 0 ? (byte)((c & 0xf)) : (byte)((c & 0xf) << 4));
                            if (nr2 == 0)
                            {
                                nr2++;
                            }
                            else
                            {
                                nr2 = 0;
                                nr++;
                            }
                        }
                er.Write((Int32)palettedImage.Length);
                er.Write((Int32)0x18);
                er.Write(palettedImage, 0, palettedImage.Length);
                er.BaseStream.Position = 8;
                er.Write((Int32)er.BaseStream.Length);
                er.BaseStream.Position = 0x14;
                er.Write((Int32)er.BaseStream.Length - 0x10);
                er.Close();
            }
        }

        private void toolStripButton4_Click(object sender, EventArgs e)
        {
            if (saveFileDialog3.ShowDialog() == System.Windows.Forms.DialogResult.OK
                && saveFileDialog3.FileName.Length > 0)
            {
                EndianBinaryWriter er = new EndianBinaryWriter(File.Create(saveFileDialog3.FileName), Endianness.LittleEndian);
                er.Write("RCSN", Encoding.ASCII, false);
                er.Write(new byte[] { 0xFF, 0xFE, 0x00, 0x01 }, 0, 4);
                er.Write((Int32)0);
                er.Write((short)0x10);
                er.Write((short)0x1);

                er.Write("NRCS", Encoding.ASCII, false);
                er.Write((Int32)0);
                er.Write((Int16)256);
                er.Write((Int16)256);
                er.Write((Int32)0);

                List<int> palnr = new List<int>();
                palnr.AddRange(paltilenr);
                /*for (int i = 0; i < 11; i++)
                {
                    for (int j = 0; j < 10; j++)
                    {
                        palnr[t.tileMap[i, j]] = paltilenr[i * 32 + j];
                    }
                }*/

                er.Write((Int32)0x800);
                /*for (int i = 0; i < 32; i++)
                {
                    for (int j = 0; j < 32; j++)
                    {
                        int npalette = (palnr[t.tileMap[j, i]] & 0xf) << 12;
                        int yFlip = (0 & 0x1) << 11;
                        int xFlip = (0 & 0x1) << 10;
                        int data = npalette + yFlip + xFlip + (t.tileMap[i, j] & 0x3FF);
                        er.Write((ushort)data);  
                    }
                }*/
                for (int i = 0; i < 0x22C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                int nr = 0;
                int nr2 = 0;
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2*10+nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                nr = 0;
                nr2++;
                for (int i = 0; i < 0x2C / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                for (int i = 0; i < 0x0A; i++)
                {
                    int npalette = (selectedpalettes[nr, nr2] & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (nr2 * 10 + nr + 1 & 0x3FF);
                    er.Write((ushort)data);
                    nr++;
                }
                for (int i = 0; i < 0x340 / 2; i++)
                {
                    int npalette = (0 & 0xf) << 12;
                    int yFlip = (0 & 0x1) << 11;
                    int xFlip = (0 & 0x1) << 10;
                    int data = npalette + yFlip + xFlip + (0 & 0x3FF);
                    er.Write((ushort)data);
                }
                er.BaseStream.Position = 8;
                er.Write((Int32)er.BaseStream.Length);
                er.BaseStream.Position = 0x14;
                er.Write((Int32)er.BaseStream.Length - 0x10);
                er.Close();
            }
        }

        private void toolStripButton5_Click(object sender, EventArgs e)
        {
            toolStripButton2.Enabled = true;
            toolStripButton3.Enabled = true;
            toolStripButton4.Enabled = true;
            try
            {
                BackgroundWorker bw = new BackgroundWorker();
                bw.WorkerReportsProgress = true;
                bw.WorkerSupportsCancellation = true;
                bw.DoWork += new DoWorkEventHandler(generate);
                bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
                bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
                bw.RunWorkerAsync(new object[] { openFileDialog1.FileName, toolStripComboBox1.SelectedIndex, toolStripComboBox2.SelectedIndex });
            }
            catch
            {
                toolStripButton2.Enabled = false;
                toolStripButton3.Enabled = false;
                toolStripButton4.Enabled = false;
                MessageBox.Show("error");
            }
        }

        private void toolStripComboBox1_Click(object sender, EventArgs e)
        {

        }
        int lastindex1 = 5;
        int lastindex2 = 5;
        private void toolStripComboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (toolStripComboBox1.SelectedIndex)
            {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 9:
                case 10:
                case 11:
                case 12:
                case 13:
                case 14:
                case 16:
                case 17:
                case 20:
                    MessageBox.Show("This one doesn't work.");
                    toolStripComboBox1.SelectedIndex = lastindex1;
                    break;
                default:
                    lastindex1 = toolStripComboBox1.SelectedIndex;
                    break;
            }
        }

        private void toolStripComboBox2_SelectedIndexChanged(object sender, EventArgs e)
        {
            switch (toolStripComboBox2.SelectedIndex)
            {
                case 0:
                case 1:
                case 2:
                case 3:
                case 4:
                case 9:
                case 10:
                case 11:
                case 12:
                case 13:
                case 14:
                case 16:
                case 17:
                case 20:
                    MessageBox.Show("This one doesn't work.");
                    toolStripComboBox2.SelectedIndex = lastindex2;
                    break;
                default:
                    lastindex2 = toolStripComboBox2.SelectedIndex;
                    break;
            }
        }

        private void toolStripTextBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            if (char.IsNumber(e.KeyChar) == false)
            {
                e.Handled = false;
            }
        }
        bool zoom = true;
        private void pictureBox2_Paint(object sender, PaintEventArgs e)
        {
            if (pictureBox2.Image != null)
            {
                e.Graphics.Clear(pictureBox2.BackColor);
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;
                e.Graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None;
                e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                e.Graphics.DrawImage(pictureBox2.Image, 0, 0, (zoom ? 80 * 2 : 80), (zoom ? 88 * 2 : 88));
                e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                for (int x = 0; x < 10; x++)
                {
                    for (int y = 0; y < 11; y++)
                    {
                        //if (x == selected.Key && y == selected.Value)
                        //{

                        // }
                        //else
                        //{
                        e.Graphics.DrawRectangle(Pens.Black, x * (zoom ? 8 * 2 : 8), y * (zoom ? 8 * 2 : 8), (zoom ? 8 * 2 : 8), (zoom ? 8 * 2 : 8));
                        e.Graphics.DrawString(selectedpalettes[x, y].ToString(), new Font(SystemFonts.DefaultFont.Name, (zoom ? 5f * 2f : 5f)), new SolidBrush(Color.Black), x * (zoom ? 8 * 2 : 8), y * (zoom ? 8 * 2 : 8));
                        //}
                    }
                }
                if (selected.Count != 0)
                {
                    for (int i = 0; i < selected.Count; i++)
                    {
                        e.Graphics.DrawRectangle(Pens.White, selected[i].Key * (zoom ? 8 * 2 : 8), selected[i].Value * (zoom ? 8 * 2 : 8), (zoom ? 8 * 2 : 8), (zoom ? 8 * 2 : 8));
                    }
                }
            }
        }
        List<KeyValuePair<int, int>> selected = new List<KeyValuePair<int, int>>();
        byte[,] selectedpalettes = new byte[10, 11];
        private void pictureBox2_MouseUp(object sender, MouseEventArgs e)
        {
            pictureBox2.Focus();
            bool shift = (Control.ModifierKeys & Keys.Shift) == Keys.Shift;
            if (e.X < (zoom ? 80 * 2 : 80) && e.Y < (zoom ? 88 * 2 : 88) && e.Button == System.Windows.Forms.MouseButtons.Left)
            {
                if (shift && !selected.Contains(new KeyValuePair<int, int>(e.X / (zoom ? 8 * 2 : 8), e.Y / (zoom ? 8 * 2 : 8))))
                {
                    selected.Add(new KeyValuePair<int, int>(e.X / (zoom ? 8 * 2 : 8), e.Y / (zoom ? 8 * 2 : 8)));
                }
                else if (shift && selected.Contains(new KeyValuePair<int, int>(e.X / (zoom ? 8 * 2 : 8), e.Y / (zoom ? 8 * 2 : 8))) && selected.Count > 1)
                {
                    selected.Remove(new KeyValuePair<int, int>(e.X / (zoom ? 8 * 2 : 8), e.Y / (zoom ? 8 * 2 : 8)));
                }
                else if(!shift)
                {
                    selected.Clear();
                    selected.Add(new KeyValuePair<int, int>(e.X / (zoom ? 8 * 2 : 8), e.Y / (zoom ? 8 * 2 : 8)));
                }
                //if (!numericUpDown1.Enabled)
                //{
                //    numericUpDown1.Enabled = true;
                //}
                //numericUpDown1.Value = selectedpalettes[selected.Key, selected.Value];
                pictureBox2.Refresh();
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            zoom = !zoom;
            pictureBox2.Refresh();
        }

        private void numericUpDown1_ValueChanged(object sender, EventArgs e)
        {
            //selectedpalettes[selected.Key, selected.Value] = (byte)numericUpDown1.Value;
            //pictureBox2.Refresh();
        }
        //bool shift = false;
        private void CoursePictureGenerator_KeyDown(object sender, KeyEventArgs e)
        {
            //if (e.KeyData == Keys.Shift)
            //{
                //shift = true;
            //}
        }

        private void CoursePictureGenerator_KeyUp(object sender, KeyEventArgs e)
        {
            //if (e.KeyData == Keys.Shift)
            //{
            //    shift = false;
            //}
        }

        private void CoursePictureGenerator_KeyPress(object sender, KeyPressEventArgs e)
        {
            
        }

        private void pictureBox2_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
        {
            char KeyChar = (char)e.KeyValue;
            if (selected.Count != 0 && Char.IsNumber(KeyChar))
            {
                if (Convert.ToInt32(KeyChar.ToString()) < 7)
                {
                    for (int i = 0; i < selected.Count; i++)
                    {
                        selectedpalettes[selected[i].Key, selected[i].Value] = (byte)(Convert.ToInt32(KeyChar.ToString()));
                    }
                    pictureBox2.Refresh();
                }
            }
        }
    }
}
